setClass("BCEClusterScore",contains="ExternalClusterScore",
		prototype=prototype(
				.description=" BCubed External Score class"
		
		)
)  

#global functions

#helper functions

#calculates BCubed precision and recall of given point
#INPUT:
#	pointNumber - number of point
#	clusters - cluster numeric vector
#	labels - labels(classes) numeric vector
#RETURNS:
#	c(precision,recall) - numeric vector contains precision and recall
PaRCalculate <-function(pointNumber,clusters,labels){
	
	clusterSet <- which(clusters==clusters[pointNumber])
	clusterSetCard <- length(clusterSet)
	
	labelSet <- which(labels==labels[pointNumber])
	labelSetCard <- length(labelSet)
	
	CaLIntersection <- intersect(clusterSet, labelSet)
	CaLIntersectionCard <- length(CaLIntersection)
	
	precision <- CaLIntersectionCard/clusterSetCard
	recall <- CaLIntersectionCard/labelSetCard
	
	return(c(precision,recall))
}
#methods

#calclustes BCubed External Score 
#for given classes and clusters
setMethod("ScoreSet",
		signature="BCEClusterScore",
		definition=function(.Object,inputSet,clusters,...){
			#check for X, Y and clusters
			callNextMethod(.Object,inputSet,clusters,...)
			if(length(inputSet$Y) != length(clusters)){
				stop("length of clusters and labels vectors must be equal ")
			}
			
			#sweep over all points and calculate precision and recall. save it as matrix
			PaRmatrix <-matrix(unlist(
							lapply( 1:length(clusters),FUN=PaRCalculate,clusters,inputSet$Y ) )
							,ncol=2,byrow=TRUE)
			#calculate precision and recall sums
			
			PaRsums <- colSums(PaRmatrix)#PaRsums[1] precision sum; PaRsums[2] recall sum
			
			BCubed <-{2*PaRsums[1]*PaRsums[2]}/{length(clusters)*{PaRsums[1]+PaRsums[2]}}
			
			
			return(BCubed) # 1-max 0 min
		}
)    

